package com.tianxiabuyi.model.pojo;

import com.alibaba.fastjson.annotation.JSONField;
import com.tianxiabuyi.Input;
import com.tianxiabuyi.Message;
import com.tianxiabuyi.model.base.TXBYObject;
import com.tianxiabuyi.persist.DBTools;
import com.tianxiabuyi.persist.QBuilder;
import com.tianxiabuyi.persist.Where;
import com.tianxiabuyi.utils.ConstantUtil;
import com.tianxiabuyi.utils.Tools;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.*;

@Entity
@Table(name = "hospital_token")
public class HospitalToken extends TXBYObject{
    /**
     * hospital_user表自增id
     */
    private Integer uid;

    /**
     * 生成的令牌
     */
    private String token;

    /**
     * 用户名
     */
    @Column(name="username")@JSONField(name = "user_name")
    private String userName;

    /**
     * 密码
     */
    private String password;

    /**
     * 令牌失效秒数
     */
    @Column(name="expire_in")@JSONField(name = "expire_in")
    private Integer expireIn;

    public HospitalToken() {
        expireIn = 1 * 60 * 60; // 默认3600秒
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getExpireIn() {
        return expireIn;
    }

    public void setExpireIn(Integer expireIn) {
        this.expireIn = expireIn;
    }

    /**
     * 验证令牌
     * 如果验证通过返回状态码0，否则返回其它状态码
     * @param input: 请求对象
     * @return: 令牌验证结果
     */
    public static Message validateToken(Input input) {
        Message message = new Message();

        // 校验参数
        String tokenString = input.getDesc("token", "");
        int hospital = input.getInt("hospital", 0);
        if (tokenString.isEmpty() || hospital == 0) {
            message.setErrcode(20001);
            return message;
        }

        // 数据库查询
        List<HospitalToken> hospitalTokenList = QBuilder.db("basedb").select().from("HospitalToken ht").where(new Where("ht.hospital=", hospital).and("ht.token=", tokenString)).page(1, 1).query().getResultObj();
        if (hospitalTokenList == null || hospitalTokenList.isEmpty()) {
            message.setErrcode(20004);
            return message;
        }

        HospitalToken hospitalToken = hospitalTokenList.get(0);
        Integer status = Tools.getInt(hospitalToken.getStatus(), 2);
        if (status == 3) {
            message.setErrcode(20003);
            return message;
        }

        // 延迟20秒，防止客户端没过期，传递到服务端过期了
        int expireIn = 1000 * (Tools.getInt(hospitalToken.getExpireIn(), 0) + 20);
        Long createAt = Tools.getLong(hospitalToken.getcTime() + "", 0L);
        Long now = System.currentTimeMillis();
        if (now > createAt + expireIn) {
            message.setErrcode(20002);
            return message;
        }

        message.setErrmsg("token验证成功");
        message.put("token", hospitalToken);
        return message;
    }

    /**
     * 删除令牌
     * @param input: 请求对象
     * @return: 删除结果描述
     */
    public static Message revokeToken(Input input) {
        Message message = new Message();

        // 校验参数
        String tokenString = input.getDesc("token", "");
        int hospital = input.getInt("hospital", 0);
        if (tokenString.isEmpty() || hospital == 0) {
            message.setErrcode(20001);
            return message;
        }

        // 数据库查询
        List<HospitalToken> hospitalTokenList = QBuilder.db("basedb").select().from("HospitalToken ht").where(new Where("ht.hospital=", hospital).and("ht.token=", tokenString)).page(1, 1).query().getResultObj();
        if (hospitalTokenList == null || hospitalTokenList.isEmpty()) {
            message.setErrcode(20004);
            return message;
        }
        HospitalToken hospitalToken = hospitalTokenList.get(0);

        // 校验状态
        Integer status = Tools.getInt(hospitalToken.getStatus(), 2);
        if (status == 3) {
            message.setErrcode(20003);
            return message;
        }

        // 删除
        QBuilder.db("basedb").execHQL("delete from HospitalToken ht where ht.hospital= '" + hospital + "' and ht.token='" + tokenString + "'");
        message.setErrmsg("token已清除");
        return message;
    }

    /**
     * 更新令牌
     * 如果更新成功返回状态码0，否则返回其它状态码
     * @param input: 请求对象
     * @param expiresIn: 令牌有效时间秒数，如果为0则默认原来的
     * @return: 令牌更新结果描述
     */
    public static Message refreshToken(Input input, int expiresIn) {
        Message message = new Message();

        // 校验参数
        String tokenString = input.getDesc("token", "");
        int hospital = input.getInt("hospital", 0);
        if (tokenString.isEmpty() || hospital == 0) {
            message.setErrcode(20001);
            return message;
        }

        // 数据库查询
        List<HospitalToken> hospitalTokenList = QBuilder.db("basedb").select().from("HospitalToken ht").where(new Where("ht.hospital=", hospital).and("ht.token=", tokenString)).page(1, 1).query().getResultObj();
        if (hospitalTokenList == null || hospitalTokenList.isEmpty()) {
            message.setErrcode(20004);
            return message;
        }
        HospitalToken hospitalToken = hospitalTokenList.get(0);

        // 校验状态
        Integer status = Tools.getInt(hospitalToken.getStatus(), 2);
        if (status == 3) {
            message.setErrcode(20003);
            return message;
        }

        // 修改创建时间
        Long now = System.currentTimeMillis();
        hospitalToken.setcTime(now);
        String userName = Tools.getDesc(hospitalToken.getUserName(), "");
        String password = Tools.getDesc(hospitalToken.getPassword(), "");
        if (0 == expiresIn) {
            expiresIn = Tools.getInt(hospitalToken.getExpireIn(), ConstantUtil.EXPIRES_IN);
        }
        String newTokenString = Tools.getMD5(userName + now + password);
        hospitalToken.setToken(newTokenString);
        hospitalToken.setExpireIn(expiresIn);

        DBTools.db("basedb").modItem(hospitalToken, hospitalToken.getId());

        message.setErrmsg("token更新成功");
        message.put("token", newTokenString);
        message.put("expiresIn", expiresIn);
        return message;
    }

    /**
     * 更新令牌
     * 如果更新成功返回状态码0，否则返回其它状态码<br>
     * @param input 请求对象
     * @return 令牌更新结果描述
     */
    public static Message refreshToken(Input input) {
        int expiresIn = 0;
        return refreshToken(input, expiresIn);
    }

    /**
     * 生成HospitalToken对象保存到数据库，并且将所有属性和属性值放入Map中返回
     * @return: Token所有属性键值对
     */
    public Map genToken() {
        // 手机客户端
        String token = Tools.getMD5(userName + getcTime() + password);
        setToken(token);
        DBTools.db("basedb").addItem(this);
        return toMap();
    }
}
